#pragma once

#include "../adapter.h"
#include "utils/random.h"

namespace burn {

class GFunction : public GAdapter {
public:
  /**
   * 设置执行函数具体内容
   * @param type
   * @param func
   * @return
   */
  GFunction *setFunction(const CFunctionType &type,
                         CGRAPH_CSTATUS_CONST_FUNCTION_REF func) {
    CGRAPH_ASSERT_INIT_RETURN_NULL(false)
    CGRAPH_ASSERT_NOT_NULL_RETURN_NULL(func)

    switch (type) {
    case CFunctionType::INIT:
      init_function_ = func;
      break;
    case CFunctionType::RUN:
      run_function_ = func;
      break;
    case CFunctionType::DESTROY:
      destroy_function_ = func;
      break;
    default:
      return nullptr; // 不可能出现的情况
    }

    return this;
  }

  CGRAPH_DECLARE_GPARAM_MANAGER_WRAPPER

protected:
  explicit GFunction() {
    this->element_type_ = GElementType::FUNCTION;
    session_ = URandom<>::generateSession(CGRAPH_STR_FUNCTION);
  };

  CStatus init() override {
    return init_function_ ? init_function_() : CStatus();
  }

  CStatus run() override { return run_function_ ? run_function_() : CStatus(); }

  CStatus destroy() override {
    return destroy_function_ ? destroy_function_() : CStatus();
  }

private:
  CGRAPH_CSTATUS_FUNCTION init_function_ = nullptr;
  CGRAPH_CSTATUS_FUNCTION run_function_ = nullptr;
  CGRAPH_CSTATUS_FUNCTION destroy_function_ = nullptr;

  friend class GPipeline;
};

using GFunctionPtr = GFunction *;

} // namespace burn